﻿/****************************************************
	文件：Program.cs
	作者：WithoutUmbrella_Boy
	邮箱: 1026188730@qq.com
	日期：2021/02/11 11:37   	
	功能：工厂方法模式
*****************************************************/
using System;
/*在简单工厂模式中讲到简单工厂模式的缺点，有一点是——简单工厂模式系统难以扩展，一旦添加新产品就不得不修改简单工厂方法，
这样就会造成简单工厂的实现逻辑过于复杂，然而本专题介绍的工厂方法模式可以解决简单工厂模式中存在的这个问题，下面就具体看看工厂模式是如何解决该问题的。

工厂方法模式的实现：工厂方法模式之所以可以解决简单工厂的模式，是因为它的实现把具体产品的创建推迟到子类中，此时工厂类不再负责所有产品的创建，
而只是给出具体工厂必须实现的接口，这样工厂方法模式就可以允许系统不修改工厂类逻辑的情况下来添加新产品，这样也就克服了简单工厂模式中缺点。
下面看下工厂模式的具体实现代码（这里还是以简单工厂模式中点菜的例子来实现）*/

#region 工厂方法模式   
/// <summary>
/// 菜抽象类
/// </summary>
public abstract class Food
{
    // 输出点了什么菜
    public abstract void Print();
}

/// <summary>
/// 西红柿炒鸡蛋这道菜
/// </summary>
public class TomatoScrambledEggs : Food
{
    public override void Print()
    {
        Console.WriteLine("西红柿炒蛋好了！");
    }
}

/// <summary>
/// 土豆肉丝这道菜
/// </summary>
public class ShreddedPorkWithPotatoes : Food
{
    public override void Print()
    {
        Console.WriteLine("土豆肉丝好了");
    }
}

/// <summary>
/// 抽象工厂类
/// </summary>
public abstract class Creator
{
    // 工厂方法
    public abstract Food CreateFoodFactory();
}

/// <summary>
/// 西红柿炒蛋工厂类
/// </summary>
public class TomatoScrambledEggsFactory : Creator
{
    /// <summary>
    /// 负责创建西红柿炒蛋这道菜
    /// </summary>
    /// <returns></returns>
    public override Food CreateFoodFactory()
    {
        return new TomatoScrambledEggs();
    }
}

/// <summary>
/// 土豆肉丝工厂类
/// </summary>
public class ShreddedPorkWithPotatoesFactory : Creator
{
    /// <summary>
    /// 负责创建土豆肉丝这道菜
    /// </summary>
    /// <returns></returns>
    public override Food CreateFoodFactory()
    {
        return new ShreddedPorkWithPotatoes();
    }
}

/*使用工厂方法实现的系统，如果系统需要添加新产品时，我们可以利用多态性来完成系统的扩展，对于抽象工厂类和具体工厂中的代码都不需要做任何改动。
例如，我们我们还想点一个“肉末茄子”，此时我们只需要定义一个肉末茄子具体工厂类和肉末茄子类就可以。
而不用像简单工厂模式中那样去修改工厂类中的实现（具体指添加case语句)。具体代码为：*/
/// <summary>
/// 肉末茄子这道菜
/// </summary>
public class MincedMeatEggplant : Food
{
    /// <summary>
    /// 重写抽象类中的方法
    /// </summary>
    public override void Print()
    {
        Console.WriteLine("肉末茄子好了");
    }
}
/// <summary>
/// 肉末茄子工厂类，负责创建肉末茄子这道菜
/// </summary>
public class MincedMeatEggplantFactory : Creator
{
    /// <summary>
    /// 负责创建肉末茄子这道菜
    /// </summary>
    /// <returns></returns>
    public override Food CreateFoodFactory()
    {
        return new MincedMeatEggplant();
    }
}

/// <summary>
/// 客户端调用
/// </summary>
class Client
{
    static void Main(string[] args)
    {
        // 初始化做菜的两个工厂（）
        Creator shreddedPorkWithPotatoesFactory = new ShreddedPorkWithPotatoesFactory();
        Creator tomatoScrambledEggsFactory = new TomatoScrambledEggsFactory();
        // 如果客户又想点肉末茄子了
        // 再另外初始化一个肉末茄子工厂
        Creator minceMeatEggplantFactor = new MincedMeatEggplantFactory();

        // 开始做西红柿炒蛋
        Food tomatoScrambleEggs = tomatoScrambledEggsFactory.CreateFoodFactory();
        tomatoScrambleEggs.Print();

        //开始做土豆肉丝
        Food shreddedPorkWithPotatoes = shreddedPorkWithPotatoesFactory.CreateFoodFactory();
        shreddedPorkWithPotatoes.Print();

        //开始做肉末茄子
        Food minceMeatEggplant = minceMeatEggplantFactor.CreateFoodFactory();
        minceMeatEggplant.Print();

        Console.ReadKey();
    }
}
#endregion

#region 总结
/*工厂方法模式通过面向对象编程中的多态性来将对象的创建延迟到具体工厂中，从而解决了简单工厂模式中存在的问题，
也很好地符合了开放封闭原则（即对扩展开发，对修改封闭）。*/
#endregion